"""
文件名: videos.py
描述: 视频内容管理API路由

本模块包含以下主要功能：
1. 用户视频内容聚合展示
2. 视频筛选和排序
3. 视频详情获取
4. 视频观看状态管理

依赖模块:
   - fastapi: Web框架路由
   - services: 视频和YouTube服务
   - models: 数据模型

使用示例:
   >>> GET /videos - 获取聚合视频内容
   >>> GET /videos/{id} - 获取视频详情
   >>> PUT /videos/{id}/watch - 标记视频为已观看
   >>> GET /videos/trending - 获取热门视频

注意事项:
   - 视频数据会定期缓存更新
   - 支持多种筛选和排序选项
   - 观看状态仅保存在本地数据库
   - 视频内容依赖YouTube API配额

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
import uuid

from fastapi import APIRouter, Depends, HTTPException, status, Query
from pydantic import BaseModel

from src.api.dependencies import (
    get_current_user,
    get_video_service,
    get_youtube_service,
    get_pagination_params,
)
from src.core.logger import get_logger
from src.models.user import User
from src.models.video import VideoInDB, VideoSummary
from src.services.video_service import VideoService
from src.services.youtube_service import YouTubeService
from src.utils.exceptions import (
    ValidationException,
    AuthorizationException,
    QuotaExceededException,
)

logger = get_logger(__name__)

router = APIRouter()


class VideoWatchRequest(BaseModel):
    """视频观看状态请求模型"""
    watched: bool = True
    watch_time: Optional[float] = None
    progress: Optional[float] = None


@router.get("", response_model=List[VideoSummary], summary="获取聚合视频内容")
async def get_aggregated_videos(
    current_user: User = Depends(get_current_user),
    video_service: VideoService = Depends(get_video_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    category_id: Optional[uuid.UUID] = Query(None, description="筛选指定分类的视频"),
    channel_id: Optional[uuid.UUID] = Query(None, description="筛选指定频道的视频"),
    published_after: Optional[str] = Query(None, description="发布时间筛选（ISO格式）"),
    duration_filter: Optional[str] = Query(None, description="时长筛选: short, medium, long"),
    quality_filter: Optional[str] = Query(None, description="画质筛选: hd, 4k"),
    sort_by: str = Query("published_at", description="排序字段: published_at, views, title"),
    sort_order: str = Query("desc", description="排序方向: asc, desc"),
    unwatch_only: bool = Query(False, description="仅显示未观看视频"),
) -> List[VideoSummary]:
    """
    获取用户的聚合视频内容
    
    Args:
        category_id: 分类ID筛选
        channel_id: 频道ID筛选
        published_after: 发布时间筛选
        duration_filter: 时长筛选
        quality_filter: 画质筛选
        sort_by: 排序字段
        sort_order: 排序方向
        unwatch_only: 仅显示未观看
        pagination: 分页参数
        
    Returns:
        List[VideoSummary]: 视频摘要列表
    """
    try:
        videos = await video_service.get_aggregated_videos(
            current_user.id,
            category_id=category_id,
            channel_id=channel_id,
            published_after=published_after,
            duration_filter=duration_filter,
            quality_filter=quality_filter,
            sort_by=sort_by,
            sort_order=sort_order,
            unwatch_only=unwatch_only,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        # 转换为摘要格式
        summaries = []
        for video in videos:
            summary = VideoSummary(
                id=video.id,
                youtube_id=video.youtube_id,
                title=video.title,
                description=video.description[:200] + "..." if len(video.description) > 200 else video.description,
                thumbnail_url=video.thumbnail_url,
                duration=video.duration,
                published_at=video.published_at,
                view_count=video.view_count,
                like_count=video.like_count,
                channel_title=video.channel_title,
                channel_thumbnail=video.channel_thumbnail,
                is_watched=video.is_watched,
                watch_progress=video.watch_progress,
            )
            summaries.append(summary)
        
        logger.info(f"获取聚合视频成功", user_id=str(current_user.id), count=len(summaries))
        return summaries
        
    except Exception as e:
        logger.error(f"获取聚合视频失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取视频内容失败"
        )


@router.get("/trending", response_model=List[VideoSummary], summary="获取热门视频")
async def get_trending_videos(
    current_user: User = Depends(get_current_user),
    video_service: VideoService = Depends(get_video_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
    time_range: str = Query("day", description="时间范围: day, week, month"),
    category_id: Optional[uuid.UUID] = Query(None, description="筛选指定分类"),
) -> List[VideoSummary]:
    """
    获取用户订阅频道的热门视频
    
    Args:
        time_range: 时间范围
        category_id: 分类筛选
        pagination: 分页参数
        
    Returns:
        List[VideoSummary]: 热门视频列表
    """
    try:
        # 计算时间范围
        time_ranges = {
            "day": timedelta(days=1),
            "week": timedelta(weeks=1),
            "month": timedelta(days=30),
        }
        
        published_after = datetime.utcnow() - time_ranges.get(time_range, timedelta(days=1))
        
        videos = await video_service.get_trending_videos(
            current_user.id,
            published_after=published_after.isoformat(),
            category_id=category_id,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        # 转换为摘要格式
        summaries = []
        for video in videos:
            summary = VideoSummary(
                id=video.id,
                youtube_id=video.youtube_id,
                title=video.title,
                thumbnail_url=video.thumbnail_url,
                duration=video.duration,
                published_at=video.published_at,
                view_count=video.view_count,
                like_count=video.like_count,
                channel_title=video.channel_title,
                channel_thumbnail=video.channel_thumbnail,
                trending_score=video.trending_score if hasattr(video, 'trending_score') else 0,
            )
            summaries.append(summary)
        
        logger.info(f"获取热门视频成功", user_id=str(current_user.id), time_range=time_range)
        return summaries
        
    except Exception as e:
        logger.error(f"获取热门视频失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取热门视频失败"
        )


@router.get("/{video_id}", response_model=VideoInDB, summary="获取视频详细信息")
async def get_video_detail(
    video_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    video_service: VideoService = Depends(get_video_service),
) -> VideoInDB:
    """
    获取指定视频的详细信息
    
    Args:
        video_id: 视频ID
        
    Returns:
        VideoInDB: 视频详细信息
    """
    try:
        video = await video_service.get_video_by_id(video_id, current_user.id)
        if not video:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="视频不存在或无访问权限"
            )
        
        logger.info(f"获取视频详情成功", video_id=str(video_id), title=video.title)
        return video
        
    except HTTPException:
        raise
    except AuthorizationException as e:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"获取视频详情失败: {e}", video_id=str(video_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取视频详情失败"
        )


@router.put("/{video_id}/watch", summary="更新视频观看状态")
async def update_video_watch_status(
    video_id: uuid.UUID,
    watch_request: VideoWatchRequest,
    current_user: User = Depends(get_current_user),
    video_service: VideoService = Depends(get_video_service),
) -> Dict[str, str]:
    """
    更新视频的观看状态
    
    Args:
        video_id: 视频ID
        watch_request: 观看状态请求
        
    Returns:
        Dict[str, str]: 更新结果
    """
    try:
        success = await video_service.update_watch_status(
            video_id,
            current_user.id,
            watched=watch_request.watched,
            watch_time=watch_request.watch_time,
            progress=watch_request.progress,
        )
        
        if not success:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="视频不存在或无访问权限"
            )
        
        status_text = "已观看" if watch_request.watched else "未观看"
        logger.info(f"视频观看状态更新成功", video_id=str(video_id), status=status_text)
        
        return {"message": f"视频状态已更新为{status_text}"}
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新视频观看状态失败: {e}", video_id=str(video_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新观看状态失败"
        )


@router.get("/statistics/summary", summary="获取视频统计摘要")
async def get_video_statistics(
    current_user: User = Depends(get_current_user),
    video_service: VideoService = Depends(get_video_service),
    time_range: str = Query("week", description="统计时间范围: day, week, month"),
) -> Dict[str, Any]:
    """
    获取用户的视频观看统计信息
    
    Args:
        time_range: 统计时间范围
        
    Returns:
        Dict[str, Any]: 统计摘要
    """
    try:
        # 计算时间范围
        time_ranges = {
            "day": timedelta(days=1),
            "week": timedelta(weeks=1),
            "month": timedelta(days=30),
        }
        
        since = datetime.utcnow() - time_ranges.get(time_range, timedelta(weeks=1))
        
        stats = await video_service.get_user_video_statistics(
            current_user.id,
            since=since,
        )
        
        logger.info(f"获取视频统计成功", user_id=str(current_user.id), time_range=time_range)
        return stats
        
    except Exception as e:
        logger.error(f"获取视频统计失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取统计信息失败"
        )


@router.post("/refresh", summary="刷新视频内容")
async def refresh_video_content(
    current_user: User = Depends(get_current_user),
    video_service: VideoService = Depends(get_video_service),
    category_ids: Optional[List[uuid.UUID]] = Query(None, description="刷新指定分类的视频"),
    max_videos_per_channel: int = Query(10, description="每个频道最大获取视频数"),
) -> Dict[str, Any]:
    """
    刷新用户的视频内容缓存
    
    Args:
        category_ids: 指定分类列表
        max_videos_per_channel: 每个频道最大获取数量
        
    Returns:
        Dict[str, Any]: 刷新结果
    """
    try:
        # 检查用户认证状态
        if not current_user.youtube_access_token:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="需要YouTube授权才能刷新视频"
            )
        
        result = await video_service.refresh_user_videos(
            current_user.id,
            category_ids=category_ids,
            max_videos_per_channel=max_videos_per_channel,
        )
        
        logger.info(f"视频内容刷新完成", user_id=str(current_user.id), result=result)
        
        return {
            "message": "视频内容刷新完成",
            "stats": result,
        }
        
    except HTTPException:
        raise
    except APIQuotaException as e:
        raise HTTPException(
            status_code=status.HTTP_429_TOO_MANY_REQUESTS,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"刷新视频内容失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="刷新视频内容失败"
        )